namespace OFX.Aggregator.Implementation.ViaVerde
{
	using System;
	using System.Collections.Generic;
	using System.Globalization;
	using System.IO;
	using System.Xml.Linq;

	using Infrastructure;

	public class XmlStatementInterpreter : IStatementInterpreter
	{
		#region IStatementInterpreter Members

		public Statement InterpretStatement(string xml)
		{
			XDocument doc = XDocument.Load(new StringReader(xml));
			XElement statementElement = doc.Element("EXTRACTO");
			XElement clientElement = statementElement.Element("CLIENTE");
			var statement = new Statement {Currency = "EUR", Date = DateTime.Now, Account = {BankId = "Brisa, SA", Number = clientElement.Attribute("id").Value, Type = AccountType.CreditLine, Holder = clientElement.Element("NOME").Value,}};

			var creditTransactionsDictionary = new Dictionary<DateTime, double>();

			foreach (var identifierElement in statementElement.Elements("IDENTIFICADOR"))
			{
				var identifier = new PaymentOriginator {Id = identifierElement.Attribute("id").Value};

				foreach (var transactionElement in identifierElement.Elements("TRANSACCAO"))
				{
					string postedHour = GetValue(transactionElement, "HORA");
					string postedDate = GetValue(transactionElement, "DATA");
					string dateTime = string.Format("{0} {1}", postedDate, postedHour);
					DateTime datePosted = DateTime.ParseExact(dateTime, "yyyy-MM-dd HH:mm", null, DateTimeStyles.AssumeLocal);

					var statementLine = new StatementLine { Amount = -double.Parse(GetValue(transactionElement, "IMPORTANCIA"), NumberStyles.Currency, NumberFormatInfo.InvariantInfo), DatePosted = datePosted, TransactionType = TransactionType.POS, TransactionId = dateTime, Description = "Brisa, SA", Memo = string.Format("{0}: {1}", GetValue(transactionElement, "TIPO"), GetValue(transactionElement, "DESCRITIVO")) };

					string valueHour = GetValue(transactionElement, "HORA_ENTRADA");
					string valueDate = GetValue(transactionElement, "DATA_ENTRADA");
					valueHour = valueHour.Trim(new[] {'-'});
					valueDate = valueDate.Trim(new[] {'-'});
					if (string.IsNullOrEmpty(valueHour))
						valueHour = postedHour;
					if (string.IsNullOrEmpty(valueDate))
						valueDate = postedDate;

					dateTime = string.Format("{0} {1}", valueDate, valueHour);
					statementLine.DateValue = DateTime.ParseExact(dateTime, "yyyy-MM-dd HH:mm", null, DateTimeStyles.AssumeLocal);

					XElement creditDateElement = transactionElement.Element("DATA_DEBITO");
					if (creditDateElement != null)
					{
						DateTime creditDate = DateTime.ParseExact(creditDateElement.Value, "yyyy-MM-dd", null, DateTimeStyles.AssumeLocal);
						double amount;

						if (creditTransactionsDictionary.TryGetValue(creditDate, out amount))
							creditTransactionsDictionary[creditDate] = amount + statementLine.Amount;
						else
							creditTransactionsDictionary[creditDate] = statementLine.Amount;
					}

					identifier.StatementLines.Add(statementLine);
				}

				statement.PaymentOriginators.Add(identifier);
			}

			var creditPaymentOriginator = new PaymentOriginator();

			foreach (var kvp in creditTransactionsDictionary)
			{
				var statementLine = new StatementLine {Amount = -kvp.Value, DatePosted = kvp.Key, TransactionType = TransactionType.Transfer, TransactionId = string.Format("Payment:{0}", kvp.Key), Description = "Transfer"};

				creditPaymentOriginator.StatementLines.Add(statementLine);
			}

			statement.PaymentOriginators.Add(creditPaymentOriginator);

			StatementInterpreterHelper.InferStatementDates(statement);

			return statement;
		}

		private static string GetValue(XContainer element, string propertyName)
		{
			if (element == null) throw new ArgumentNullException("element");

			return element.Element(propertyName).Value;
		}

		#endregion
	}
}